//
// Created by luolijun on 2021/11/1.
//

#include "FacadePrototypeRepoImpl.h"

#include "src/facade/builtin/FacadePrototypeProviderBuiltin.h"

#include "utils/asserts.h"

#include <QDebug>

namespace falcon {

FacadePrototypeRepoImpl::FacadePrototypeRepoImpl() {
    baseid = 0;
}

FacadePrototypeRepoImpl::~FacadePrototypeRepoImpl() {
}

int32_t FacadePrototypeRepoImpl::registerPrototype(std::string groupName, Facade* fc) {
    auto itrGroup = groups.find(groupName);
    if (itrGroup == groups.end()) {
        int32_t newId = baseid++;
        prototypes.insert({ newId, fc });
        groups.insert({ groupName, std::list<int32_t> { newId } });
        return newId;
    }

    int32_t newId = baseid++;
    prototypes.insert({ newId, fc });
    itrGroup->second.push_back(newId);

    return newId;
}

void FacadePrototypeRepoImpl::enumPrototypeGroup(std::function<int(std::string groupName)> callback) {
    for (auto item : groups) {
        if (callback(item.first) != 0) {
            break;
        }
    }
}

void FacadePrototypeRepoImpl::enumPrototype(std::string groupName, std::function<int(Facade* fc)> callback) {
    if (groupName.empty()) {
        for (auto item : groups) {
            for (int32_t id : item.second) {
                if (callback(prototypes[id]) != 0) {
                    return;
                }
            }
        }

        return;
    }

    auto groupItems = groups[groupName];
    for (int32_t id : groupItems) {
        if (callback(prototypes[id]) != 0) {
            return;
        }
    }
}

Facade* FacadePrototypeRepoImpl::clonePrototype(int32_t tmplId, std::string name, int32_t id) {
    auto itr = prototypes.find(tmplId);
    if (itr != prototypes.end()) {
        return nullptr;
    }

    Facade* fc = itr->second->clone();
    ASSERT(fc != nullptr);

    return fc;
}

extern FacadePrototypeRepo* CreateFacadeRepo() {
    return new FacadePrototypeRepoImpl();
}

extern int LoadBuiltinPrototypes(FacadePrototypeRepo* repo) {
    Q_ASSERT(repo != nullptr);
    FacadePrototypeProviderBuiltin prov;
    prov.Setup(*repo);
    return 0;
}

} // namespace falcon